home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / mus / play / DeliDecrunch.lha / src / Decruncher.c < prev    next >
C/C++ Source or Header  |  2000-10-15  |  8KB  |  216 lines

  1. /* DeliDecruncher (C) 2000 Stuart Caie <kyzer@4u.net>
  2.  *
  3.  * This program is free software; you can redistribute it and/or modify
  4.  * it under the terms of the GNU General Public License as published by
  5.  * the Free Software Foundation; either version 2 of the License, or
  6.  * (at your option) any later version.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program; if not, write to the Free Software
  15.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17.  
  18. #include <dos/dosextens.h>
  19. #include <exec/execbase.h>
  20. #include <exec/memory.h>
  21. #include <libraries/xadmaster.h>
  22. #include <libraries/xfdmaster.h>
  23. #include <proto/dos.h>
  24. #include <proto/exec.h>
  25. #include <proto/xadmaster.h>
  26. #include <proto/xfdmaster.h>
  27. #include "DeliPlayer.h"
  28.  
  29. static const char version[] = "$VER: Decruncher 2.1 (15.10.2000)";
  30. static char TempFile[] = "T:DeliDecr.dat";
  31. static const char MatchStr[] = "~(#?displayme#?|#?readme#?|#?liesmich#?|"
  32.   "#?.diz|#?.info|#?.doc|#?.dok|#?.txt|#?.text|#?.exe|#?.lst)";
  33.  
  34.  
  35. /* tries to allocate memory for and load a file, writes filelen to *lenptr */
  36. APTR LoadFile(STRPTR filename, LONG *lenptr, ULONG memflags, DELIBASE) {
  37.   struct DosLibrary *DOSBase = DeliBase->dtg_DOSBase;
  38.   struct FileInfoBlock *fib;
  39.   APTR file = NULL, mem;
  40.   BPTR lock, fh;
  41.   LONG len;
  42.  
  43.   /* lots of code just to find out file size... */
  44.   if ((fib = (struct FileInfoBlock *)
  45.              AllocDosObject(DOS_FIB, NULL))) {
  46.  
  47.     if ((lock = Lock(filename, SHARED_LOCK))) {
  48.       if (Examine(lock, fib) && fib->fib_DirEntryType < 0) {
  49.         len = fib->fib_Size;
  50.  
  51.         /* allocate enough memory with requested flags. */
  52.         /* if that fails, just use any public memory    */
  53.         mem = AllocListData((ULONG) len, memflags);
  54.         if (!mem) mem = AllocListData((ULONG) len, MEMF_ANY | MEMF_PUBLIC);
  55.         if (mem) {
  56.  
  57.           /* read in the file */
  58.           if ((fh = OpenFromLock(lock))) {
  59.             if (Read(fh, mem, len) >= 0) {
  60.               file = mem;
  61.               mem = NULL;
  62.               *lenptr = len;
  63.             }
  64.             Close(fh);
  65.           }
  66.           if (mem) FreeListData(mem);
  67.         }
  68.       }
  69.       UnLock(lock);
  70.     }
  71.     FreeDosObject(DOS_FIB, (APTR) fib);
  72.   }
  73.   return file;
  74. }
  75.  
  76. /* This performs the decrunching of a file for DeliTracker.
  77.  * - Deli loads 1kb of the file (full filename in dtg_PathArrayPtr), this
  78.  *   1kb is shown by dtg_CheckData and dtg_CheckSize
  79.  * - the decruncher examines it, allocates memory WITH dtg_AllocListData()
  80.  * - the decruncher frees all memory and returns 1 for failure/unknown format
  81.  * - the decruncher doesn't free the actual mod's memory, but frees all
  82.  *   others, and returns 0 for a successful recognition and decrunch
  83.  */
  84. ULONG Decrunch(DELIBASE) {
  85.   struct ExecBase *SysBase = *((struct ExecBase **) 4UL);
  86.   struct DosLibrary *DOSBase = DeliBase->dtg_DOSBase;
  87.  
  88.   struct xadArchiveInfo *xai;
  89.   struct xadFileInfo *chosen, *xfi;
  90.   struct xadMasterBase *xadMasterBase;
  91.   struct xfdBufferInfo *xbi;
  92.   struct xfdMasterBase *xfdMasterBase;
  93.  
  94.   UBYTE patbuf[sizeof(MatchStr)*2+2];
  95.   struct TagItem tags[3];
  96.   ULONG len, err=1;
  97.   APTR buf;
  98.   BPTR fh;
  99.  
  100.   /* just in case the tempfile already exists, try to delete it */
  101.   SetProtection(TempFile, 0);
  102.   DeleteFile(TempFile);
  103.  
  104.   /* try to open xadmaster, to see if the file is an archive */
  105.   if ((xadMasterBase = (struct xadMasterBase *)
  106.                        OpenLibrary(XADNAME, 4))) {
  107.  
  108.     if ((xai = (struct xadArchiveInfo *)
  109.                xadAllocObjectA(XADOBJ_ARCHIVEINFO, NULL))) {
  110.  
  111.       /* examine file - is it an archive? */
  112.       tags[0].ti_Tag  = XAD_INFILENAME;
  113.       tags[0].ti_Data = (ULONG) DeliBase->dtg_PathArrayPtr;
  114.       tags[1].ti_Tag  = TAG_DONE;
  115.  
  116.       if (!xadGetInfoA(xai, tags)) {
  117.  
  118.         /* yes, this is an archive. Now, see if there are any files in the
  119.          * archive that fit a certain filename criteria (ie not *.txt, etc)
  120.          * and 'choose' the first acceptable file.
  121.          */
  122.         chosen = NULL;
  123.         ParsePatternNoCase((STRPTR) MatchStr, patbuf, sizeof(patbuf));
  124.         for (xfi = xai->xai_FileInfo; (xfi); xfi = xfi->xfi_Next) {
  125.           if (MatchPatternNoCase(patbuf, FilePart(xfi->xfi_FileName))) {
  126.             chosen = xfi; break;
  127.           }
  128.         }
  129.  
  130.         /* if an acceptable file was found, try to extract it */
  131.         if (chosen) {
  132.           tags[0].ti_Tag  = XAD_ENTRYNUMBER;
  133.           tags[0].ti_Data = (ULONG) chosen->xfi_EntryNumber;
  134.           tags[1].ti_Tag  = XAD_OUTFILENAME;
  135.           tags[1].ti_Data = (ULONG) TempFile;
  136.           tags[2].ti_Tag  = TAG_DONE;
  137.  
  138.           /* err=0 on success, <>0 on error */
  139.           err = xadFileUnArcA(xai, tags);
  140.         }
  141.         xadFreeInfo(xai);
  142.       }
  143.       xadFreeObjectA(xai, NULL);
  144.     }
  145.     CloseLibrary((APTR) xadMasterBase);
  146.   }
  147.  
  148.   /* as file isn't an archive (or no XAD is present),  let's try to decrunch
  149.    * it with XFD...
  150.    */
  151.   if (err) {
  152.     if ((xfdMasterBase = (struct xfdMasterBase *)
  153.                          OpenLibrary(XFDM_NAME, 36))) {
  154.  
  155.       if ((xbi = (struct xfdBufferInfo *)
  156.                  xfdAllocObject(XFDOBJ_BUFFERINFO))) {
  157.  
  158.         /* try to load the full file */
  159.         if ((buf = LoadFile(DeliBase->dtg_PathArrayPtr,
  160.                             &len, MEMF_PUBLIC, DeliBase))) {
  161.  
  162.           xbi->xfdbi_SourceBuffer = buf;
  163.           xbi->xfdbi_SourceBufLen = len;
  164.           xbi->xfdbi_Flags = XFDFF_RECOGEXTERN;
  165.  
  166.           /* if we recognize the format, and it isn't encrypted... */
  167.           if (xfdRecogBuffer(xbi) && (xbi->xfdbi_PackerFlags &
  168.              (XFDPFF_PASSWORD|XFDPFF_KEY16|XFDPFF_KEY32)) == 0) {
  169.  
  170.             /* ...decrunch it */
  171.             xbi->xfdbi_TargetBufMemType = MEMF_ANY;
  172.             if (xfdDecrunchBuffer(xbi)) {
  173.  
  174.               /* decrunching was successful. try to write to the tempfile */
  175.               if ((fh = Open(TempFile, MODE_NEWFILE))) {
  176.                 err = (Write(fh, xbi->xfdbi_TargetBuffer,
  177.                        xbi->xfdbi_TargetBufSaveLen) < 0);
  178.                 Close(fh);
  179.               }
  180.               FreeMem(xbi->xfdbi_TargetBuffer, xbi->xfdbi_TargetBufLen);
  181.             }
  182.           }
  183.           FreeListData(buf);
  184.         }
  185.         xfdFreeObject((APTR) xbi);
  186.       }
  187.       CloseLibrary((APTR) xadMasterBase);
  188.     }
  189.   }
  190.  
  191.   if (!err) {
  192.     /* now ensure the file is both readable and deletable */
  193.     SetProtection(TempFile, 0);
  194.     /* try to read in the file */
  195.     err = (LoadFile(TempFile, &len, MEMF_PUBLIC|MEMF_CHIP, DeliBase) == NULL);
  196.     /* delete the file, in any instance */
  197.     DeleteFile(TempFile);
  198.   }
  199.   return err;
  200. }
  201.  
  202.  
  203. const struct TagItem PlayerTags[] = {
  204.   { DTP_RequestDTVersion,    17 },
  205.   { DTP_PlayerVersion,       (2<<16)|(1) },
  206.   { DTP_PlayerName,          (ULONG) "Decruncher" },
  207.   { DTP_Creator,             (ULONG) "written by Kyzer/CSG <kyzer@4u.net>,\n"
  208.                                      "XAD by Dirk Stöcker and others,\n"
  209.                                      "XFD by Georg Hörmann and others" },
  210.   { DTP_Description,         (ULONG) "this genie decrunches compressed mods\n"
  211.                                      "using the XAD dearchiving library and\n"
  212.                                      "the XFD decrunching library" },
  213.   { DTP_Decrunch,            (ULONG) Decrunch },
  214.   { TAG_DONE,                0 }
  215. };
  216.